package cn.edu.nwpu.warehousemanagement.service.impl;

import cn.edu.nwpu.warehousemanagement.config.RsaKeyConfig;
import cn.edu.nwpu.warehousemanagement.constantEnum.UserRole;
import cn.edu.nwpu.warehousemanagement.dao.UserRepository;
import cn.edu.nwpu.warehousemanagement.pojo.Result;
import cn.edu.nwpu.warehousemanagement.pojo.User;
import cn.edu.nwpu.warehousemanagement.pojo.request.*;
import cn.edu.nwpu.warehousemanagement.pojo.response.JWTResponse;
import cn.edu.nwpu.warehousemanagement.service.UserService;
import cn.edu.nwpu.warehousemanagement.util.*;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * 用户服务实现类
 *
 * @author Loadstar
 * @version 1.0
 */
@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserRepository userRepository;
    @Resource
    private RsaKeyConfig rsaKeyConfig;
    @Resource
    private RedisUtil redisUtil;

    @Override
    public User findByUserName(String username) {
        return userRepository.findByUsername(username);
    }

    @Override
    public User findById(Long id) {
        return userRepository.findByIdAndDeletedFalse(id);
    }

    //获取当前登录用户,每次都要先查再更新，感觉不如直接编写Update sql高效 todo
    public User getLoginUser() {
        return findById(ThreadLocalUtil.getLoginUserId());
    }


    /**
     * @return 当前登录用户ID
     * @Deprecated
     */
    private static Long getLoginUserId() {
        Map<String, Object> tlMap = ThreadLocalUtil.get();
        Object idObj = tlMap.get("id");
        return (idObj instanceof Integer)
                ? ((Integer) idObj).longValue()
                : (Long) idObj;
    }

    private String getToken(String username, User loginUser) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", loginUser.getId());
        claims.put("username", username);
        String token = JwtUtil.getToken(claims);
        redisUtil.putJWT(loginUser.getId(), token, 3, TimeUnit.HOURS);
        return token;
    }

    @Override
    public Result<?> register(RegisterRequest registerRequest) {
        return register(registerRequest.getUsername(), registerRequest.getPassword(),
                registerRequest.getRealname(), registerRequest.getPhone(),
                registerRequest.getEmail(), registerRequest.getRole());
    }

    @Override
    public Result<?> register(String username, String password, String realName, String phone, String email, String role) {
        // 检查用户名是否已存在
        if (userRepository.findByUsername(username) != null) {
            LogUtil.error(UserServiceImpl.class, "用户名已被占用, 用户名: {}", username);
            return Result.error("用户名已被占用");
        }
        try {
            //rsa解密
            String plainPassword = rsaKeyConfig.decrypt(password);
            // 校验信息是否合法(用正则表达式做了）,密码强度是否符合要求 todo

            //应用强哈希算法bcrypt，并加盐值
            String encryptedPassword = BcryptUtil.hashPassword(plainPassword);
            //将String role 转为 UserRole
            UserRole userRole = UserRole.valueOf(role);

            userRepository.save(new User(username, encryptedPassword, realName, email, phone, userRole));
            return Result.success();
        } catch (IllegalArgumentException e) {
            LogUtil.error(UserServiceImpl.class, "传入参数错误", e);
            return Result.error("无效的角色类型，传入参数错误");
        }
    }

    @Override
    public Result<?> getUserInfo() {
        User loginUser = getLoginUser();
        if (null == loginUser) {
            return Result.error("请求错误");
        }
        User retUser = new User(loginUser.getUsername(), null, loginUser.getRealName(), loginUser.getEmail(), loginUser.getPhone(), loginUser.getRole());
        return Result.success(retUser);
    }

    @Override
    public Result<?> updateUserInfo(UpdateSelfInfoRequest request) {
        String realName = request.getRealname();
        String phone = request.getPhone();
        String email = request.getEmail();

        User loginUser = getLoginUser();

        if (StringUtils.hasLength(realName)) {
            loginUser.setRealName(realName);
        }
        if (StringUtils.hasLength(phone)) {
            loginUser.setPhone(phone);
        }
        if (StringUtils.hasLength(email)) {
            loginUser.setEmail(email);
        }

        userRepository.save(loginUser);

        return Result.success("用户信息更新成功");

    }


    @Override
    public Result<?> login(LoginRequest request, String token) {
        //判断是否已经登录过
        if (null != token) {
            if (null != redisUtil.getJWT(token)) {
                //跳转到首页
                return Result.error("已登录,将跳转");
            }
        }

//        if (null != ThreadLocalUtil.get()) {
//            //跳转到首页
//            return Result.error("已登录,将跳转");
//        }

        String plainPassword = rsaKeyConfig.decrypt(request.getPassword());
        return login(request.getUsername(), plainPassword);
    }

    @Override
    public Result<?> login(String username, String password) {

        User loginUser = this.findByUserName(username);
        //判断是否有该用户
        if (loginUser != null) {
            if (BcryptUtil.verifyPassword(password, loginUser.getPassword())) {
                //密码正确
                String token = getToken(username, loginUser);
                JWTResponse response = new JWTResponse(token);
                return Result.success(response);
            } else {
                return Result.error("密码错误");
            }
        } else {
            return Result.error("用户名错误");
        }
    }

    @Override
    public Result<?> easyLogin(LoginRequest request, String token) {
        //判断是否已经登录过
        if (null != token) {
            if (null != redisUtil.getJWT(token)) {
                //跳转到首页
                return Result.error("已登录,将跳转");
            }
        }
        User loginUser = this.findByUserName(request.getUsername());
        String newToken = getToken(request.getUsername(), loginUser);
        JWTResponse response = new JWTResponse(newToken);
        return Result.success(response);

    }

    @Override
    public Result<?> logout(String token) {
        if (null != token) {
            if (null != redisUtil.getJWT(token)) {
                redisUtil.deleteCurrentJWT(token, ThreadLocalUtil.getLoginUserId());
                return Result.success("退出成功");
            }
        }
        return Result.error("未登录");
    }


    @Override
    public Result<?> updatePassword(UpdatePWRequest params, String token) {
        // 校验新旧密码
        String oldPassword = BcryptUtil.hashPassword(params.getOldPassword());
        String newPassword = params.getNewPassword();
        String repeatPassword = params.getRepeatPassword();
        if (!StringUtils.hasLength(oldPassword) || !StringUtils.hasLength(newPassword) || !StringUtils.hasLength(repeatPassword)) {
            return Result.error("未输入完整");
        }
        if (!newPassword.equals(repeatPassword)) {
            return Result.error("两次输入密码不一致");
        }
        // 校验旧密码是否正确
        User loginUser = getLoginUser();
        if (BcryptUtil.verifyPassword(oldPassword, loginUser.getPassword())) {
            userRepository.updatePasswordById(loginUser.getId(), BcryptUtil.hashPassword(newPassword));
            redisUtil.deleteAllJWTsByIdWithLua(ThreadLocalUtil.getLoginUserId());
            return Result.success("修改成功，请重新登录");
        } else {
            return Result.error("旧密码错误");
        }
    }

    public Result<?> adminUpdatePassword(AdminUpdatePWRequest params) {
        // 校验新旧密码
        String newPassword = params.getNewPassword();
        String repeatPassword = params.getRepeatPassword();

        if (!newPassword.equals(repeatPassword)) {
            return Result.error("两次输入密码不一致");
        }
        User updatedUser = findById(params.getId());
        updatedUser.setPassword(BcryptUtil.hashPassword(newPassword));
        userRepository.save(updatedUser);
        redisUtil.deleteAllJWTsByIdWithLua(params.getId());
        return Result.success("修改成功，请重新登录");

    }


}
